package com.webcamtracker.move.gestures;

import com.webcamtracker.move.tracking.TrackingEvent;
import com.webcamtracker.move.tracking.TrackingEventDispacher;
import com.webcamtracker.move.tracking.TrackingEventListener;
import com.webcamtracker.move.tracking.TrackingEventType;

import java.util.List;
import java.util.Vector;

/**
 * Main class for move gestures.
 * <br>Sample usage:
 * <code><pre>
 *      MoveGestures moveGestures = new MoveGestures(trackingEventDispacher);
 *      moveGestures.addMoveGesturesListener(myMoveGesturesListener);
 *      moveGestures.start();</pre>
 * </code>
 *
 * @author Smardec
 * @version 1.2
 */
public class MoveGestures
{
    /**
     * Responsible for monitoring move gestures.
     */
    private TrackingEventListener trackingGesturesEventListener = null;

    /**
     * Responsible for processing move events.
     */
    private MoveGesturesRecognizer moveGesturesRecognizer;

    /**
     * Vector of listeners.
     */
    private Vector<MoveGesturesListener> listeners = new Vector<MoveGesturesListener>();

    /**
     * It�s the one in charge of dispaching all tracking events for MoveGestures to process them
     */
    private TrackingEventDispacher eventDispacher;


    public MoveGestures(TrackingEventDispacher eventDispacher)
    {
        this.eventDispacher = eventDispacher;
        this.moveGesturesRecognizer = new MoveGesturesRecognizer(this); 
    }

    /**
     * Starts monitoring move gestures.
     */
    public void start()
    {
        if (trackingGesturesEventListener == null)
        {
            trackingGesturesEventListener = new TrackingEventListener()
            {
                public void trackingEventDispatched(TrackingEvent event)
                {
                    if (event.getType().isChanged())
                    {
                        moveGesturesRecognizer.processMoveEvent(event);
                    }

                     /*Aca van las condiciones de salida... Timer?*/
                    if (event.getType().isLost())
                    {
                        if (moveGesturesRecognizer.isGestureRecognized())
                        {
                            List<MoveType> gesture = moveGesturesRecognizer.getGesture();
                            // execute action
                            fireProcessMoveGesture(gesture);                            
                            // clear temporary information
                            moveGesturesRecognizer.clearTemporaryInfo();

                        } else
                        {
                            // clear temporary information
                            moveGesturesRecognizer.clearTemporaryInfo();
                        }
                    }
                }
            };
        }
        
        this.eventDispacher.addTrackingEventListener(trackingGesturesEventListener, TrackingEventType.ALL);
    }

    /**
     * Stops monitoring move gestures.
     */
    public void stop()
    {
        if (trackingGesturesEventListener != null)
        {
            this.eventDispacher.removeTrackingEventListener(trackingGesturesEventListener, TrackingEventType.ALL);        
        }
    }

    /**
     * Returns current grid size (minimum move movement length to be recognized).
     *
     * @return Grid size in pixels. Default is 30.
     */
    public int getGridSize() {
        return moveGesturesRecognizer.getGridSize();
    }

    /**
     * Sets grid size (minimum move movement length to be recognized).
     *
     * @param gridSize New grid size in pixels
     */
    public void setGridSize(int gridSize) {
        moveGesturesRecognizer.setGridSize(gridSize);
    }

    /**
     * Adds move gestures listener.
     *
     * @param listener Instance of {@link MoveGesturesListener}
     */
    public void addMoveGesturesListener(MoveGesturesListener listener) {
        if (listener == null)
            return;
        listeners.add(listener);
    }

    /**
     * Removes move gestures listener.
     *
     * @param listener Instance of {@link MoveGesturesListener}
     */
    public void removeMoveGesturesListener(MoveGesturesListener listener) {
        if (listener == null)
            return;
        listeners.remove(listener);
    }

    /**
     * Fires event when full move gesture is recogized (move button is released).
     *
     * @param gesture String representation of move gesture. "L" for left, "R" for right,
     */
    private void fireProcessMoveGesture(List<MoveType> gesture) {
        for (MoveGesturesListener listener : listeners) {
            listener.processGesture(gesture);
        }
    }

    /**
     * Fires event when new move movement is recognized but move gesture is not yet completed.
     *
     * @param gesture String representation of recognized movements. "L" for left, "R" for right,
     */
    void fireGestureMovementRecognized(java.util.List<MoveType> gesture) {
        for (MoveGesturesListener listener : listeners) {
            listener.gestureMovementRecognized(gesture);
        }
    }
}
